/*
    //sqlite C语言
    封装实现一个SqliteHelper类 提供简单的sqlite数据库操作接口 
    完成数据的基本增删改查操作
        1.创建/打开数据库文件
        2.针对打开的数据库执行操作
            a.表的操作
            b.数据的操作
        3.关闭数据库
*/
#pragma once
#include<sqlite3.h>
#include<string>
#include<vector>
#include<iostream>

class SqliteHelper
{
public:
    typedef int (*SqliteCallback)(void*, int, char**, char**);      //定义一个函数指针类型
    SqliteHelper(const std::string &dbfile)
        :_dbfile(dbfile)
        ,_handler(nullptr)
    {}
    bool open(int safe_leve = SQLITE_OPEN_FULLMUTEX)
    {
        //int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs );
        //以可读可写方式打开数据库 没文件就创建 安全等级串行化
        int ret = sqlite3_open_v2(_dbfile.c_str(), &_handler, SQLITE_OPEN_READWRITE| SQLITE_OPEN_CREATE | safe_leve, nullptr);
        if(ret != SQLITE_OK)
        {
            std::cout << "创建/打开sqlite 数据库失败" 
            << sqlite3_errmsg(_handler) << std::endl;
            return false;
        }
        return true;
    }
    
    bool execute(const std::string &sql, SqliteCallback cb, void *arg)  //sql 语句 cb回调函数 arg缓冲区
    {
        //int sqlite3_exec(sqlite3*, char *sql, int (*callback)(void*,int,char**,char**), void* arg, char **err)
        //int (*callback)(void*,int,char**,char**)
        //void* arg: 是设置的在回调时传⼊的arg参数
        //int：⼀⾏中数据的列数
        //char**：存储⼀⾏数据的字符指针数组
        //char**：每⼀列的字段名称
        int ret = sqlite3_exec(_handler, sql.c_str(), cb, arg, nullptr);
        if (ret != SQLITE_OK)
        {   
            std::cout << sql << std::endl;
            std::cout << "执行语句失败" << sqlite3_errmsg(_handler) << std::endl;
            return false;
        }

        return true;
    }
    void close()
    {
        //int sqlite3_close(sqlite3* db); 成功返回SQLITE_OK
        if(_handler) sqlite3_close_v2(_handler);
    }
private:
    std::string _dbfile;
    sqlite3 *_handler;
};